package com.it.schoolhomeos.controller;

import com.it.schoolhomeos.dto.ApiResponse;
import com.it.schoolhomeos.entity.Notification;
import com.it.schoolhomeos.entity.User;
import com.it.schoolhomeos.enums.NotificationStatus;
import com.it.schoolhomeos.enums.NotificationTargetRole;
import com.it.schoolhomeos.enums.NotificationType;
import com.it.schoolhomeos.repository.UserRepository;
import com.it.schoolhomeos.service.NotificationService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.List;

/**
 * 通知控制器
 * 
 * 处理通知、公告、新闻等信息的CRUD操作
 * 提供发布、查询、更新和删除通知的功能
 */
@RestController
@RequestMapping("/api/notifications")
@Tag(name = "通知管理", description = "通知、公告、新闻等信息管理")
public class NotificationController {

    private static final Logger logger = LoggerFactory.getLogger(NotificationController.class);

    /**
     * 通知服务，用于处理通知相关业务逻辑
     */
    @Autowired
    private NotificationService notificationService;

    /**
     * 用户服务，用于处理用户相关业务逻辑
     */
    @Autowired
    private UserRepository userRepository;

    /**
     * 获取通知列表接口
     * 
     * @param type 通知类型，可选参数
     * @param targetRole 目标角色，可选参数
     * @param classId 班级ID，可选参数
     * @param status 通知状态，可选参数，默认为PUBLISHED
     * @param page 页码，默认为0
     * @param size 每页大小，默认为10
     * @return 分页的通知列表
     */
    @GetMapping
    @Operation(summary = "获取通知列表", description = "分页获取通知列表")
    public ApiResponse<Page<Notification>> getNotifications(
            @Parameter(description = "通知类型") @RequestParam(required = false) String type,
            @Parameter(description = "目标角色") @RequestParam(required = false) String targetRole,
            @Parameter(description = "班级ID") @RequestParam(required = false) Long classId,
            @Parameter(description = "通知状态") @RequestParam(required = false) NotificationStatus status,
            @Parameter(description = "页码") @RequestParam(defaultValue = "0") int page,
            @Parameter(description = "每页大小") @RequestParam(defaultValue = "10") int size) {
        
        logger.debug("获取通知列表 - 参数: type={}, targetRole={}, classId={}, status={}, page={}, size={}", 
                type, targetRole, classId, status, page, size);
        
        Pageable pageable = PageRequest.of(page, size);
        Page<Notification> notifications;
        
        // 使用传入的状态参数，不设置默认值
        NotificationStatus queryStatus = status;
        logger.debug("查询状态: {}", queryStatus);

        try {
            if (type != null && targetRole != null && classId != null) {
                logger.debug("查询条件: 类型+角色+班级");
                notifications = notificationService.getNotificationsByTypeAndStatusAndClassId(
                        NotificationType.valueOf(type), queryStatus, classId, pageable);
            } else if (type != null && targetRole != null) {
                logger.debug("查询条件: 类型+角色");
                notifications = notificationService.getNotificationsByTypeAndStatusAndTargetRole(
                        NotificationType.valueOf(type), queryStatus, NotificationTargetRole.valueOf(targetRole), pageable);
            } else if (type != null) {
                logger.debug("查询条件: 类型");
                notifications = notificationService.getNotificationsByTypeAndStatus(
                        NotificationType.valueOf(type), queryStatus, pageable);
            } else {
                logger.debug("查询条件: {}", status == null ? "所有状态" : "指定状态");
                if (status == null) {
                    notifications = notificationService.getAllNotifications(pageable);
                } else {
                    notifications = notificationService.getNotificationsByTypeAndStatus(null, queryStatus, pageable);
                }
            }
            
            logger.debug("查询结果: 总条数={}, 总页数={}", 
                    notifications.getTotalElements(), notifications.getTotalPages());
            return ApiResponse.success(notifications);
        } catch (Exception e) {
            logger.error("获取通知列表失败", e);
            return ApiResponse.error(500, "获取通知列表失败: " + e.getMessage());
        }
    }

    /**
     * 获取通知详情接口
     * 
     * @param id 通知ID
     * @return 通知详情
     */
    @GetMapping("/{id}")
    @Operation(summary = "获取通知详情", description = "根据ID获取通知详情")
    public ApiResponse<Notification> getNotification(@PathVariable Long id) {
        Notification notification = notificationService.getNotificationById(id);
        return ApiResponse.success(notification);
    }

    /**
     * 发布通知接口
     * 
     * @param notification 通知对象
     * @return 创建成功的通知
     */
    @PostMapping
    @Operation(summary = "发布通知", description = "发布新的通知")
    public ApiResponse<Notification> createNotification(@RequestBody Notification notification) {
        try {
            // 设置当前登录用户为发布者
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            String username = authentication.getName();
            logger.debug("当前用户: {}", username);
            
            // 需要从数据库中查询用户
            User currentUser = userRepository.findByUsername(username)
                    .orElseThrow(() -> new RuntimeException("用户不存在"));
            notification.setPublisher(currentUser);
            
            // 由于新的接口需要附件和封面图片参数，这里传入空值
            List<MultipartFile> attachments = new ArrayList<>();
            MultipartFile coverImage = null;
            
            Notification createdNotification = notificationService.createNotification(notification, attachments, coverImage);
            //默认不置顶
            setNotificationTopStatus(createdNotification.getId(),false);

            return ApiResponse.success("发布成功", createdNotification);
        } catch (Exception e) {
            logger.error("发布通知失败", e);
            return ApiResponse.error(500, "发布通知失败: " + e.getMessage());
        }
    }

    /**
     * 发布带附件的通知接口
     * 
     * @param notification 通知对象
     * @param attachments 附件列表
     * @param coverImage 封面图片
     * @return 创建成功的通知
     */
    @PostMapping("/with-files")
    @Operation(summary = "发布带附件的通知", description = "发布带附件和封面图片的新通知")
    public ApiResponse<Notification> createNotificationWithFiles(
            @RequestPart("notification") Notification notification,
            @RequestPart(value = "attachments", required = false) List<MultipartFile> attachments,
            @RequestPart(value = "coverImage", required = false) MultipartFile coverImage) {
        
        try {
            // 设置当前登录用户为发布者
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            String username = authentication.getName();
            logger.debug("当前用户: {}", username);
            
            // 需要从数据库中查询用户
            User currentUser = userRepository.findByUsername(username)
                    .orElseThrow(() -> new RuntimeException("用户不存在"));
            notification.setPublisher(currentUser);
            
            Notification createdNotification = notificationService.createNotification(notification, attachments, coverImage);
            return ApiResponse.success("发布成功", createdNotification);
        } catch (Exception e) {
            logger.error("发布带附件的通知失败", e);
            return ApiResponse.error(500, "发布带附件的通知失败: " + e.getMessage());
        }
    }

    /**
     * 更新通知接口
     * 
     * @param id 通知ID
     * @param notification 更新后的通知对象
     * @return 更新后的通知
     */
    @PutMapping("/{id}")
    @Operation(summary = "更新通知", description = "更新已有通知")
    public ApiResponse<Notification> updateNotification(
            @PathVariable Long id, 
            @RequestBody Notification notification) {
        
        try {
            // 获取原有通知
            Notification existingNotification = notificationService.getNotificationById(id);
            if (existingNotification == null) {
                return ApiResponse.error(404, "通知不存在");
            }
            
            // 设置ID和发布者，确保不会被修改
            notification.setId(id);
            notification.setPublisher(existingNotification.getPublisher());
            
            // 确保必要字段不为空
            if (notification.getTargetRole() == null) {
                notification.setTargetRole(existingNotification.getTargetRole());
            }
            if (notification.getType() == null) {
                notification.setType(existingNotification.getType());
            }
            if (notification.getStatus() == null) {
                notification.setStatus(existingNotification.getStatus());
            }
            if (notification.getIsTop() == null) {
                notification.setIsTop(existingNotification.getIsTop());
            }
            
            // 由于新的接口需要附件和封面图片参数，这里传入空值
            List<MultipartFile> attachments = new ArrayList<>();
            MultipartFile coverImage = null;
            
            Notification updatedNotification = notificationService.updateNotification(notification, attachments, coverImage);
            return ApiResponse.success("更新成功", updatedNotification);
        } catch (Exception e) {
            logger.error("更新通知失败", e);
            return ApiResponse.error(500, "更新通知失败: " + e.getMessage());
        }
    }

    /**
     * 更新带附件的通知接口
     * 
     * @param id 通知ID
     * @param notification 更新后的通知对象
     * @param attachments 附件列表
     * @param coverImage 封面图片
     * @return 更新后的通知
     */
    @PutMapping("/{id}/with-files")
    @Operation(summary = "更新带附件的通知", description = "更新带附件和封面图片的通知")
    public ApiResponse<Notification> updateNotificationWithFiles(
            @PathVariable Long id,
            @RequestPart("notification") Notification notification,
            @RequestPart(value = "attachments", required = false) List<MultipartFile> attachments,
            @RequestPart(value = "coverImage", required = false) MultipartFile coverImage) {
        
        try {
            // 获取原有通知
            Notification existingNotification = notificationService.getNotificationById(id);
            if (existingNotification == null) {
                return ApiResponse.error(404, "通知不存在");
            }
            
            // 设置ID和发布者，确保不会被修改
            notification.setId(id);
            notification.setPublisher(existingNotification.getPublisher());
            
            // 确保必要字段不为空
            if (notification.getTargetRole() == null) {
                notification.setTargetRole(existingNotification.getTargetRole());
            }
            if (notification.getType() == null) {
                notification.setType(existingNotification.getType());
            }
            if (notification.getStatus() == null) {
                notification.setStatus(existingNotification.getStatus());
            }
            if (notification.getIsTop() == null) {
                notification.setIsTop(existingNotification.getIsTop());
            }
            
            Notification updatedNotification = notificationService.updateNotification(notification, attachments, coverImage);
            return ApiResponse.success("更新成功", updatedNotification);
        } catch (Exception e) {
            logger.error("更新带附件的通知失败", e);
            return ApiResponse.error(500, "更新带附件的通知失败: " + e.getMessage());
        }
    }

    /**
     * 删除通知接口
     * 
     * @param id 通知ID
     * @return 删除结果
     */
    @DeleteMapping("/{id}")
    @Operation(summary = "删除通知", description = "删除指定通知")
    public ApiResponse<Void> deleteNotification(@PathVariable Long id) {
        notificationService.deleteNotification(id);
        return ApiResponse.<Void>success("删除成功", null);
    }
    
    /**
     * 设置通知置顶状态
     * 
     * @param id 通知ID
     * @param isTop 是否置顶
     * @return 更新后的通知
     */
    @PutMapping("/{id}/top")
    @Operation(summary = "设置通知置顶状态", description = "设置通知是否置顶")
    public ApiResponse<Notification> setNotificationTopStatus(
            @PathVariable Long id,
            @RequestParam Boolean isTop) {
        Notification notification = notificationService.setNotificationTopStatus(id, isTop);
        return ApiResponse.success("设置成功", notification);
    }
    
    /**
     * 更新通知状态
     * 
     * @param id 通知ID
     * @param status 通知状态
     * @return 更新后的通知
     */
    @PutMapping("/{id}/status")
    @Operation(summary = "更新通知状态", description = "更新通知的状态")
    public ApiResponse<Notification> updateNotificationStatus(
            @PathVariable Long id,
            @RequestParam NotificationStatus status) {
        Notification notification = notificationService.updateNotificationStatus(id, status);
        return ApiResponse.success("更新成功", notification);
    }
    
    /**
     * 获取置顶通知列表
     * 
     * @param status 通知状态
     * @return 置顶通知列表
     */
    @GetMapping("/top")
    @Operation(summary = "获取置顶通知列表", description = "获取所有置顶的通知")
    public ApiResponse<List<Notification>> getTopNotifications(
            @RequestParam(required = false, defaultValue = "PUBLISHED") NotificationStatus status) {
        List<Notification> notifications = notificationService.getTopNotifications(status);
        return ApiResponse.success(notifications);
    }
    
    /**
     * 搜索通知
     * 
     * @param title 标题关键字
     * @param status 通知状态
     * @param page 页码
     * @param size 每页大小
     * @return 通知分页列表
     */
    @GetMapping("/search")
    @Operation(summary = "搜索通知", description = "根据标题关键字搜索通知")
    public ApiResponse<Page<Notification>> searchNotifications(
            @RequestParam String title,
            @RequestParam(required = false, defaultValue = "PUBLISHED") NotificationStatus status,
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size) {
        
        Pageable pageable = PageRequest.of(page, size);
        Page<Notification> notifications = notificationService.searchNotificationsByTitle(title, status, pageable);
        return ApiResponse.success(notifications);
    }
} 